import java.io.*;
import java.util.*;


/*
 * Game data will be constantly saved at each step in a game.  However, user data will only be adjusted
 * at the end of each game.  At the end of the game, both the userNames and users ArrayLists will be written to a single object file.
 * To create new games, we must call the createNewGame method.
 */

public class Model {
// Attributes
	
	int[] validXLocations = {238, 488, 738, 318, 488, 648,
							 413, 488, 553, 238, 318, 413,
							 553, 648, 738, 413, 488,
							 553, 318, 488, 648, 238, 488, 738};

	int[] validYLocations = {38, 38, 38, 108, 108, 108, 198,
							 198, 198, 298, 298, 298, 298, 298,
							 298, 388, 388, 388, 483, 483,
							 483, 558, 558, 558};
	ArrayList<String> userNames = new ArrayList<String>();		// Names of all users (stored first in user file).
	ArrayList<User> users = new ArrayList<User>();				// Objects of all users (stored in second in user file).
	ArrayList<String> gameNames = new ArrayList<String>();		// Names of all games saved (actual game object has its own file).
	
	
	Game game;

	
// Methods & Constructors
	
	public Model() throws IOException{
		obtainUsers();
		obtainGameHistory();
		updateUserFile();
	}

	public void Model(User[] users, Boolean newGameFlyingEnabled) throws IOException{
		obtainUsers();
		obtainGameHistory();
	}
	
		/*
	 * Get user names and users from the file and store them for leader board statistics
	 * and to be updated once the game ends
	 */
	public void obtainUsers() throws IOException{

		File file = new File("Users.file");
		if(!file.exists()){
			file.createNewFile();
		}
		else{
			FileInputStream fis = new FileInputStream("Users.file");
			ObjectInputStream ois = new ObjectInputStream(fis);


			try{
				setUserNames((ArrayList<String>) ois.readObject());
				setUsers((ArrayList<User>) ois.readObject());
			}
			catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			ois.close();
		}
	}
	
	public void obtainGameHistory() throws IOException{
		FileInputStream fis = new FileInputStream("GameHistory.file");
		ObjectInputStream ois = new ObjectInputStream(fis);
		
		try {
			setGameNames((ArrayList<String>) ois.readObject());
		} 
		
		catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	
		ois.close();
	}
	
	public void updateGameHistory() throws IOException{
		String fileName = "GameHistory.file";
		File file;
		file = new File(fileName);
		if(!file.exists())
		{
			file.createNewFile();
		}
		
		FileOutputStream fos = new FileOutputStream(fileName);
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		oos.writeObject(this.getGameNames());
		oos.close();
	}
	
	public void updateUserFile() throws IOException{
		String fileName = "Users.file";
		File file;
		file = new File(fileName);
		if(!file.exists())
		{
			file.createNewFile();
		}
		
		FileOutputStream fos = new FileOutputStream(fileName);
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		oos.writeObject(this.getUserNames());
		oos.writeObject(this.getUsers());
		oos.close();
	}
	
	public void createNewGame(User[] users, boolean isFlyingEnabled){
		game = new Game(users, isFlyingEnabled);
	}
	
	
	public int readPosition(int row, int column){
		return getGame().getBoardLayout()[row][column];
	}
	
	public Boolean writePosition(int row, int column, int value){
		getGame().getBoardLayout()[row][column] = value;
		return true;
	}
	
	public void adjustTokensLeft(int p1Tokens, int p2Tokens){
		int[] tokensLeft = new int[2];
		tokensLeft[0] = p1Tokens;
		tokensLeft[1] = p2Tokens;
		try {
			getGame().setTokensLeft(tokensLeft);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// The interface should be adjusted here as well.
	}

	public int returnNodeX(int index){
		int x = validXLocations[index];
		return x;
	}
	public int returnNodeY(int index){
		int y = validYLocations[index];
		return y;
	}
	public int getIndex(int x, int y){
		int index = 0;
		int[] boardLayoutX = Main.getControllerSystem().getGridtoBoardLayoutX();
		int[] boardLayoutY = Main.getControllerSystem().getGridtoBoardLayoutY();
		for(int i=0;i<24;i++){
			if(x == boardLayoutX[i] && y == boardLayoutY[i]){
				index = i;
			}
		}
		return index;
	}
	
	
// Getters & Setters
	
	public ArrayList<String> getGameNames() {
		return gameNames;
	}

	public void setGameNames(ArrayList<String> gameNames) {
		this.gameNames = gameNames;
	}

	public ArrayList<String> getUserNames() {
		return userNames;
	}

	public void setUserNames(ArrayList<String> userNames) {
		this.userNames = userNames;
	}
	
	public ArrayList<User> getUsers(){
		return users;
	}
	
	public void setUsers(ArrayList<User> users){
		this.users =users;
	}
	
	public Game getGame() {
		return game;
	}

	public void setGame(Game game) {
		this.game = game;
	}
	
	public int[] getValidXLocations() {
		return validXLocations;
	}

	public void setValidXLocations(int[] validXLocations) {
		this.validXLocations = validXLocations;
	}

	public int[] getValidYLocations() {
		return validYLocations;
	}

	public void setValidYLocations(int[] validYLocations) {
		this.validYLocations = validYLocations;
	}

}